package org.slf4j.impl;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Set;

import org.slf4j.helpers.MarkerIgnoringBase;

@SuppressWarnings("serial")
public class XtraTinyLogger extends MarkerIgnoringBase {
	private static final String DEFAULT_FORMAT = "[:level] [:date :time] [:name] :msg";
	private static final String DATE_FORMAT = "yyyy-MM-dd";
	private static final String TIME_FORMAT = "HH:mm:ss";

	private Set<XtraTinyLoggerAppender> appenders;
	private String name;
	private String format = DEFAULT_FORMAT;

	private LoggingLevel level = LoggingLevel.ERROR;

	public void setLevel(LoggingLevel level) {
		if (level != null) {
			this.level = level;
		}
	}

	public void setFormat(String format) {
		if (format != null) {
			this.format = format;
		}
	}

	public XtraTinyLogger(String name, Set<XtraTinyLoggerAppender> appenders) {
		this.name = name;
		this.appenders = appenders;
	}

	public boolean isTraceEnabled() {
		return false;
	}

	public void trace(String msg) {
		throw new UnsupportedOperationException();
	}

	public void trace(String format, Object arg) {
		throw new UnsupportedOperationException();
	}

	public void trace(String format, Object arg1, Object arg2) {
		throw new UnsupportedOperationException();
	}

	public void trace(String format, Object... arguments) {
		throw new UnsupportedOperationException();
	}

	public void trace(String msg, Throwable t) {
		throw new UnsupportedOperationException();
	}

	public boolean isDebugEnabled() {
		return level.compareTo(LoggingLevel.DEBUG) <= 0;
	}

	public void debug(String msg) {
		if (isDebugEnabled()) {
			log(LoggingLevel.DEBUG, msg);
		}
	}

	public void debug(String format, Object arg) {
		if (isDebugEnabled()) {
			log(LoggingLevel.DEBUG, format, arg);
		}
	}

	public void debug(String format, Object arg1, Object arg2) {
		if (isDebugEnabled()) {
			log(LoggingLevel.DEBUG, format, arg1, arg2);
		}
	}

	public void debug(String format, Object... arguments) {
		if (isDebugEnabled()) {
			log(LoggingLevel.DEBUG, format, arguments);
		}
	}

	public void debug(String msg, Throwable t) {
		if (isDebugEnabled()) {
			log(LoggingLevel.DEBUG, t.getMessage());
		}
	}

	public boolean isInfoEnabled() {
		return level.compareTo(LoggingLevel.INFO) <= 0;
	}

	public void info(String msg) {
		if (isInfoEnabled()) {
			log(LoggingLevel.INFO, msg);
		}
	}

	public void info(String format, Object arg) {
		if (isInfoEnabled()) {
			log(LoggingLevel.INFO, format, arg);
		}
	}

	public void info(String format, Object arg1, Object arg2) {
		if (isInfoEnabled()) {
			log(LoggingLevel.INFO, format, arg1, arg2);
		}
	}

	public void info(String format, Object... arguments) {
		if (isInfoEnabled()) {
			log(LoggingLevel.INFO, format, arguments);
		}
	}

	public void info(String msg, Throwable t) {
		if (isInfoEnabled()) {
			log(LoggingLevel.INFO, t.getMessage());
		}
	}

	public boolean isWarnEnabled() {
		return false;
	}

	public void warn(String msg) {
		throw new UnsupportedOperationException();
	}

	public void warn(String format, Object arg) {
		throw new UnsupportedOperationException();
	}

	public void warn(String format, Object... arguments) {
		throw new UnsupportedOperationException();
	}

	public void warn(String format, Object arg1, Object arg2) {
		throw new UnsupportedOperationException();
	}

	public void warn(String msg, Throwable t) {
		throw new UnsupportedOperationException();
	}

	public boolean isErrorEnabled() {
		return level.compareTo(LoggingLevel.ERROR) <= 0;
	}

	public void error(String msg) {
		if (isErrorEnabled()) {
			log(LoggingLevel.ERROR, msg);
		}
	}

	public void error(String format, Object arg) {
		if (isErrorEnabled()) {
			log(LoggingLevel.ERROR, format, arg);
		}
	}

	public void error(String format, Object arg1, Object arg2) {
		if (isErrorEnabled()) {
			log(LoggingLevel.ERROR, format, arg1, arg2);
		}
	}

	public void error(String format, Object... arguments) {
		if (isErrorEnabled()) {
			log(LoggingLevel.ERROR, format, arguments);
		}
	}

	public void error(String msg, Throwable t) {
		if (isErrorEnabled()) {
			log(LoggingLevel.ERROR, t.getMessage());
		}
	}

	public void log(LoggingLevel level, String msg) {
		String detailedMsg = compileLogEntry(format, level.toString(), msg);
		for (XtraTinyLoggerAppender appender : appenders) {
			appender.append(detailedMsg);
		}
	}

	public void log(LoggingLevel level, String format, Object... arguments) {
		String msg = replaceArguments(format, arguments);
		log(level, msg);
	}

	private String replaceArguments(String format, Object... arguments) {
		int index = 0;
		while (index < arguments.length) {
			format = format.replaceFirst("\\{\\}", arguments[index].toString());
			index++;
		}
		return format;
	}

	private String compileLogEntry(String format, String level, String msg) {
		Date now = new Date();
		return format
				.replaceAll(":level", level)
				.replaceAll(":name", name)
				.replaceAll(":msg", msg)
				.replaceAll(":date",
						new SimpleDateFormat(DATE_FORMAT).format(now))
				.replaceAll(":time",
						new SimpleDateFormat(TIME_FORMAT).format(now));
	}
}
